﻿using System;
using System.Windows.Media;

using Game.Common;
using Game.Level;
using Game.Map;

namespace Game.Command.Internal
{
    struct FightValues
    {
        public int strength;
        public int armor;
        public int damage;
        public int experience;
        public int defensebonus;
        public int attackbonus;
        public double hemming;
        public Brush brush;
        public bool kamikaze;
        public int weapcount;
    }
      
    class FightObject : AttackFormula
    {
        private FightValues _AttackValues;
        private FightValues _DefendValues;
        
        protected FightObject(
            IGameMapView gameMap,
            GameLevels levels)
            : base(gameMap, levels)
        {
            _AttackValues = new FightValues();
            _DefendValues = new FightValues();
        }
        
        public FightValues AttackValues
        {
            get { return _AttackValues; }
            set { _AttackValues=value; }
        }
        
        public FightValues DefendValues
        {
            get { return _DefendValues; }
            set { _DefendValues=value; }
        }

        //! Performs the calculation of the attack. The result is only stored in the av and dv structures and is not written to the map
        public void DoCalculation () 
        {
            var parameters = new AttackParameters();
            int damagefactor = parameters.AttackPower;
            const double armordivisor = 5;
            
            FightValues av = _AttackValues;
            FightValues dv = _DefendValues;
            
            if ( av.strength > 0 ) 
            {
                double absstrength = av.strength
                       * ( 1 + strength_experience ( av.experience ) 
                       + strength_attackbonus ( av.attackbonus ) )
                       * strength_damage ( av.damage ) 
                       * dv.hemming;
            
                double absdefense = 
                    (dv.armor / armordivisor )
                    * ( 1 + defense_defensebonus ( dv.defensebonus ) 
                    + defense_experience ( dv.experience ) );
            
                int w = (int) Math.Ceiling(
                    dv.damage + 
                    absstrength / absdefense * 1000 / damagefactor 
                    );
            
                if (dv.damage > w ) 
                {
                    Console.WriteLine("fatal error at attack: \ndecrease of damage d!");
                }
            
                if (dv.damage == w )
                {
                    w = dv.damage+1;
                }
            
                if (w > 100) 
                {
                    dv.damage = 100; 
                }
                else 
                {
                    dv.damage = w; 
                }
            
                if ( av.weapcount > 0 )
                {
                    av.weapcount--;
                }
                else
                {
                    av.weapcount = 0;
                }
            
                av.experience++;
            
                if ( dv.damage >= 100 ) 
                {
                    av.experience += 1;
                }
            
                if ( av.experience > GameParameters.MaxUnitExperience )
                {
                    av.experience = GameParameters.MaxUnitExperience;
                }
            
            } 
            
            if ( dv.strength > 0 ) 
            {
                double absstrength = (dv.strength)
                    * ( 1 + strength_experience ( dv.experience ) 
                    + strength_attackbonus ( dv.attackbonus ) )
                    * strength_damage ( dv.damage ) ;
                
                double absdefense = 
                    (av.armor / armordivisor)
                    * ( 1 + defense_defensebonus ( av.defensebonus )
                          + defense_experience ( av.experience ));
                
                int w = (int)(Math.Ceiling(
                    av.damage + 
                    absstrength / absdefense * 1000 / damagefactor )
                   );
                
                if (av.damage > w ) 
                {
                    Console.WriteLine("fatal error at attack: \ndecrease of damage a!");
                }
                
                av.damage = (w > 100) ? 100 : w;
                
                if ( dv.weapcount > 0 )
                {
                    dv.weapcount--;
                }
                else
                {
                    dv.weapcount = 0;
                }
                
                if ( av.damage >= 100 ) 
                {
                    dv.experience += 2;
                    if ( dv.experience > GameParameters.MaxUnitExperience )
                    {
                        dv.experience = GameParameters.MaxUnitExperience;
                    }
                }
                else
                {
                    if ( dv.experience < GameParameters.MaxUnitExperience )
                    {
                        dv.experience++;
                    }
                } 
            }
                
            if ( av.kamikaze ) 
            {
                av.damage = 100;
            }
            
            _AttackValues = av;
            _DefendValues = dv;
        }

        //! Writes the result of the attack calculation to the actual units.
        virtual public void SetResult(
            GameTurn turn,
            Actions.ActionExecutor executor)
        {
        }

    }
}
